﻿using System;
using System.IO;
using up6.db.model;
using Aliyun.OSS;

namespace up6.db.store.oss
{
    public class OSSTool
    {

        /// <summary>
        /// API:
        /// https://help.aliyun.com/document_detail/91093.html
        /// </summary>
        /// <param name="key">/123.txt</param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string putObject(string key, byte[] data)
        {
            OSSConfig cfg = new OSSConfig();

            // 创建OssClient实例。
            var client = new OssClient(cfg.endpoint, cfg.ak, cfg.sk);
            try
            {
                MemoryStream requestContent = new MemoryStream(data);
                // 上传文件。
                client.PutObject(cfg.bucket, key, requestContent);
                Console.WriteLine("Put object succeeded");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Put object failed, {0}", ex.Message);
            }
            return "";

        }

        public static string putObject(string key, string pathLoc)
        {
            OSSConfig cfg = new OSSConfig();

            // 创建OssClient实例。
            var client = new OssClient(cfg.endpoint, cfg.ak, cfg.sk);
            try
            {
                // 上传文件。
                client.PutObject(cfg.bucket, key, pathLoc);
                Console.WriteLine("Put object succeeded");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Put object failed, {0}", ex.Message);
            }
            return "";
        }


        /**
		 * API：
		 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_GetObject.html
		 * @param key 以左斜杠开始的资源路径。/guid/QQ.exe径
		 * @param blockOffset
		 * @param blockLen
		 * @return
		 */
        public static byte[] getObject(string key, long blockOffset, long blockLen)
        {
            OSSConfig cfg = new OSSConfig();
            // 创建OssClient实例。
            var client = new OssClient(cfg.endpoint, cfg.ak, cfg.sk);
            try
            {
                MemoryStream mem = new MemoryStream();
                var getObjectRequest = new GetObjectRequest(cfg.bucket, key);
                // 设置Range，取值范围为第20至第100字节。
                getObjectRequest.SetRange(blockOffset, blockOffset+blockLen-1);
                // 范围下载。getObjectRequest的setRange可以实现文件的分段下载和断点续传。
                var obj = client.GetObject(getObjectRequest);
                // 下载数据并写入文件。
                using (var requestStream = obj.Content)
                {
                    byte[] buf = new byte[1024];
                    //var fs = File.Open(downloadFilename, FileMode.OpenOrCreate);
                    var len = 0;
                    while ((len = requestStream.Read(buf, 0, 1024)) != 0)
                    {
                        mem.Write(buf, 0, len);
                        //fs.Write(buf, 0, len);
                    }
                    //fs.Close();
                    //Console.WriteLine("Get object succeeded");
                    return mem.ToArray();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Get object failed. {0}", ex.Message);
                throw new IOException("oss get object error");
            }
        }

        /**
		 * API：
		 * 	https://help.aliyun.com/document_detail/91103.html
		 * @param key guid/QQ.exe，
		 * @return
		 */
        public static String CreateMultipartUpload(String key)
        {
            OSSConfig cfg = new OSSConfig();
            // 创建OssClient实例。
            var client = new OssClient(cfg.endpoint, cfg.ak, cfg.sk);
            // 定义上传的文件及所属Bucket的名称。您可以在InitiateMultipartUploadRequest中设置ObjectMeta，但不必指定其中的ContentLength。
            var request = new InitiateMultipartUploadRequest(cfg.bucket, key);
            try
            {
                var result = client.InitiateMultipartUpload(request);
                if (string.IsNullOrEmpty(result.UploadId)) throw new IOException("oss CreateMultipartUpload error");
                return result.UploadId;
            }
            catch (Exception)
            {
                throw new IOException("oss CreateMultipartUpload error");
            }
        }

        /**
		 * API:
		 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_UploadPart.html
		 * @param key /guid/QQ.exe
		 * @param part 基于1
		 * @param uploadID
		 * @param data
		 */
        public static String UploadPart(String key, int part, String uploadID, byte[] data)
        {
            OSSConfig cfg = new OSSConfig();
            // 创建OssClient实例。
            var client = new OssClient(cfg.endpoint, cfg.ak, cfg.sk);
            // 定义上传的文件及所属Bucket的名称。您可以在InitiateMultipartUploadRequest中设置ObjectMeta，但不必指定其中的ContentLength。
            var request = new UploadPartRequest(cfg.bucket, key, uploadID) { 
                InputStream=new MemoryStream(data),
                PartSize=data.Length,
                PartNumber=part
            };
            var result = client.UploadPart(request);
            if (string.IsNullOrEmpty(result.PartETag.ETag)) throw new IOException("oss UploadPart error");
            return result.PartETag.ETag;
        }

        /**
		 * 参数：pathSvr,minio_id(UploadId)
		 * API:
		 * 	https://help.aliyun.com/document_detail/91103.html
		 * POST /Key+?uploadId=UploadId HTTP/1.1
			Host: Bucket.s3.amazonaws.com
			<?xml version="1.0" encoding="UTF-8"?>
			<CompleteMultipartUpload xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
			   <Part>
				  <ChecksumCRC32>string</ChecksumCRC32>
				  <ChecksumCRC32C>string</ChecksumCRC32C>
				  <ChecksumSHA1>string</ChecksumSHA1>
				  <ChecksumSHA256>string</ChecksumSHA256>
				  <ETag>string</ETag>
				  <PartNumber>integer</PartNumber>
			   </Part>
			   ...
			</CompleteMultipartUpload>

		 * @param key
		 * @param id
		 */
        public static bool CompleteMultipartUpload(FileInf file)
        {
            OSSConfig cfg = new OSSConfig();
            // 创建OssClient实例。
            var client = new OssClient(cfg.endpoint, cfg.ak, cfg.sk);
            var cmur = new CompleteMultipartUploadRequest(cfg.bucket, file.ossKey(), file.object_id);

            try
            {
                foreach (var partETag in file.ossEtags())
                {
                    cmur.PartETags.Add(partETag);
                }
                var result = client.CompleteMultipartUpload(cmur);
                return true;
            }
            catch (Exception) {
                throw new IOException("oss CompleteMultipartUpload error");
            }
        }
    }
}